# 功能模块：车间场景
# 作者：dl
# 描述：车间场景

import os
import asyncio
from gltf import GLTFLoader, GLTFRenderEngine
import random
import json
from visualizationCom.tools.color import hex_to_rgba
from visualizationCom.bussiness.com.defectsVis import load as defectLoad,selectDefect

from vtkmodules.vtkIOPLY import vtkPLYReader
from vtkmodules.vtkRenderingCore import (
    vtkGlyph3DMapper,
    vtkActor,
)
from vtkmodules.vtkCommonCore import vtkPoints
from vtkmodules.vtkCommonDataModel import (
    vtkCellArray,
    vtkPolyData
)
import time

class productScene:
    # 构造函数
    def __init__(self, parent, webState, webCtrl):
        self.parent = parent
        self.webState = webState
        self.webCtrl = webCtrl

        # 车间场景相关属性
        self.hasLoadScene = False  # 用于判断是否存在缓存
        
        self.engine = GLTFRenderEngine()
        self.renderer = self.engine.GetDefaultRenderer()    
        self.renderer.SetGround(1, scale=5)
        self.camera = self.engine.GetCamera()

        self.defectColor = hex_to_rgba('#FF0000')
        bg_color = hex_to_rgba('#132c4a')
        self.renderer.SetBackground(bg_color[0], bg_color[1], bg_color[2])

        self.actor = None

    def enterScene_mesh(self):
        self.parent.mouseInteractorEvent.outline.Clear()
        self.parent.mouseInteractorEvent.lastPick = None

        with self.webState:
            self.webState.sceneKey = 'product'

        self.parent.currentRenderer = self.renderer
        
        if self.actor == None:
            self.hasLoadScene = False
        else:
            if self.actor.GetObjectName() != 'mesh_defect_example':
                self.hasLoadScene = False

        # 暂时写死模型
        if self.hasLoadScene == False:
            CURRENT_DIRECTORY = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

            depth_image = "dataImages/defect/image_20240130104608350_20240130104609334.bmp"
            # defect_mask = "dataImages/defect/image_20240130104608350_20240130104609334.png"
            defect_mask = "dataImages/defect/image_20240130110607271_20240130110610517.png"         
            # 结合 CURRENT_DIRECTORY 和 user_input 形成新的地址
            depth_image_path = os.path.join(CURRENT_DIRECTORY, depth_image)
            defect_mask_path = os.path.join(CURRENT_DIRECTORY, defect_mask)

            self.renderer.RemoveAllViewProps()
            self.actor = defectLoad(depth_image_path,defect_mask_path,'Mesh')
            self.actor.SetObjectName('mesh_defect_example')

            center = self.actor.GetCenter()
            self.renderer.AddActor(self.actor)

            # 计算相机应该放置的位置，这里我们简单地后退一定距离
            self.camera.SetPosition(center[0], center[1], center[2] + 600)
            self.camera.SetFocalPoint(center)
            
            # 调整相机的视野覆盖范围，确保模型完整展示
            # self.camera.SetViewAngle(30)  # 可以根据模型的实际大小调整视角大小
        self.renderer.AddActor(self.actor)
        self.hasLoadScene = True

        self.parent.renderWindow.AddRenderer(self.renderer)

        # 重置交互器
        self.engine.SetRenderWindow(self.parent.renderWindow)
        self.parent.mouseInteractorEvent.SetDefaultRenderer(self.renderer)
        self.parent.mouseInteractorEvent.SetOutlineRenderer(self.engine.GetOutlineRenderer())

        self.webCtrl.view_update()

        self.webCtrl.sendMsgToParent({"eventScene":"product","eventName":"enterScene","value":"complete"})

    def leaveScene(self):
        self.parent.renderWindow.RemoveRenderer(self.renderer)

    def load_file(self, file_name):
        self.renderer.RemoveAllViewProps()

        self.reader_detail = GLTFLoader()
        self.reader_detail.Load(file_name)
        self.renderer.AddScene(self.reader_detail.GetScene())

    def changeEvn(self,bgIndex):
        if bgIndex == 1:
            # CURRENT_DIRECTORY = os.path.dirname(
            #     os.path.dirname(os.path.dirname(__file__)))

            # modePath = "3dENV/spaichingen_hill_1k.hdr"

            # # 结合 CURRENT_DIRECTORY 和 modePath 形成新的地址
            # new_directory = os.path.join(CURRENT_DIRECTORY, modePath)
            # self.renderer.SetEnvmap(new_directory)
            bg_color = hex_to_rgba('#041A21')
            self.renderer.SetBackground(bg_color[0], bg_color[1], bg_color[2])
        else:
            bg_color = hex_to_rgba('#132c4a')
            self.renderer.SetBackground(bg_color[0], bg_color[1], bg_color[2])
        self.parent.renderWindow.Render()
        self.webCtrl.view_update()
        self.webCtrl.view_update()

    def changeShowType(self,showType):
        CURRENT_DIRECTORY = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

        depth_image = "dataImages/defect/image_20240130104608350_20240130104609334.bmp"
        # defect_mask = "dataImages/defect/image_20240130104608350_20240130104609334.png"
        defect_mask = "dataImages/defect/image_20240130110607271_20240130110610517.png"
        # 结合 CURRENT_DIRECTORY 和 user_input 形成新的地址
        depth_image_path = os.path.join(CURRENT_DIRECTORY, depth_image)
        defect_mask_path = os.path.join(CURRENT_DIRECTORY, defect_mask)

        self.renderer.RemoveAllViewProps()
        actor = defectLoad(depth_image_path,defect_mask_path,showType)

        center = actor.GetCenter()
        self.renderer.AddActor(actor)

        # 计算相机应该放置的位置，这里我们简单地后退一定距离
        self.camera.SetPosition(center[0], center[1], center[2] + 600)
        self.camera.SetFocalPoint(center)

        self.parent.renderWindow.Render()
        self.webCtrl.view_update()
        self.webCtrl.view_update()

        self.webCtrl.sendMsgToParent({"eventScene":"product","eventName":"changeShowType","value":"complete"})

    def selectDefect(self,id):
        selectDefect(id)
        self.parent.renderWindow.Render()
        self.webCtrl.view_update()
        self.webCtrl.view_update()

    def enterScene(self,productItem):
        self.parent.renderWindow.AddRenderer(self.renderer)
        self.parent.mouseInteractorEvent.outline.Clear()
        self.parent.mouseInteractorEvent.lastPick = None

        with self.webState:
            self.webState.sceneKey = 'product'

        self.parent.currentRenderer = self.renderer
        
        if self.actor == None:
            self.hasLoadScene = False
        else:
            print(self.actor.GetObjectName(),'mingcheng')
            print(productItem['name'],'productItem')
            if self.actor.GetObjectName() != productItem['name']:
                self.hasLoadScene = False
            
        # 暂时写死模型
        if self.hasLoadScene == False:
            CURRENT_DIRECTORY = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

            product_path = "dataImages/product/"+productItem['name']+".ply"
       
            # 结合 CURRENT_DIRECTORY 和 user_input 形成新的地址
            current_path = os.path.join(CURRENT_DIRECTORY, product_path)

            reader = vtkPLYReader()
            reader.SetFileName(current_path)

            self.renderer.RemoveAllViewProps()

            mapper = vtkGlyph3DMapper()
            mapper.SetSourceData(self.get_point())
            mapper.SetInputConnection(reader.GetOutputPort())
            mapper.ScalarVisibilityOn()

            self.actor = vtkActor()
            self.actor.SetObjectName(productItem['name']) #用于重进场景时判断是否已加载
            self.actor.SetMapper(mapper)
            self.actor.GetProperty().SetColor(0.8, 0.7, 0.6)

            center = self.actor.GetCenter()
            self.renderer.AddActor(self.actor)

            # 计算相机应该放置的位置，这里我们简单地后退一定距离
            self.camera.SetPosition(center[0], center[1], center[2] + 600)
            self.camera.SetFocalPoint(center)
            
            # 调整相机的视野覆盖范围，确保模型完整展示
            # self.camera.SetViewAngle(30)  # 可以根据模型的实际大小调整视角大小

        self.hasLoadScene = True

        # 重置交互器
        self.engine.SetRenderWindow(self.parent.renderWindow)

        self.parent.mouseInteractorEvent.SetDefaultRenderer(self.renderer)

        self.parent.mouseInteractorEvent.SetOutlineRenderer(self.engine.GetOutlineRenderer())

        self.webCtrl.view_update()

        self.webCtrl.sendMsgToParent({"eventScene":"product","eventName":"enterScene","value":"complete"})

    def get_point(self):
        points = vtkPoints()
        p = [0, 0, 0]
        vertices = vtkCellArray()
        pid = [0]
        pid[0] = points.InsertNextPoint(p)
        vertices.InsertNextCell(1, pid)
        point = vtkPolyData()
        point.SetPoints(points)
        point.SetVerts(vertices)
        return point

    # 预加载测试代码
    def preload(self,name):
        # CURRENT_DIRECTORY = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

        # product_path = "dataImages/product/"+name+".ply"
    
        # # 结合 CURRENT_DIRECTORY 和 user_input 形成新的地址
        # current_path = os.path.join(CURRENT_DIRECTORY, product_path)

        # start_time = time.time()
        # reader = vtkPLYReader()
        # reader.SetFileName(current_path)
        # end_time1 = time.time()
        # elapsed_time1 = end_time1 - start_time

        # print("读取耗时：", elapsed_time1, "秒")

        # self.renderer.RemoveAllViewProps()

        # mapper = vtkGlyph3DMapper()
        # mapper.SetSourceData(self.get_point())
        # mapper.SetInputConnection(reader.GetOutputPort())
        # mapper.ScalarVisibilityOn()

        # self.actor = vtkActor()
        # self.actor.SetMapper(mapper)
        # self.actor.GetProperty().SetColor(0.8, 0.7, 0.6)

        # center = self.actor.GetCenter()
        # self.renderer.AddActor(self.actor)

        # # 计算相机应该放置的位置，这里我们简单地后退一定距离
        # self.camera.SetPosition(center[0], center[1], center[2] + 600)
        # self.camera.SetFocalPoint(center)

        # self.hasLoadScene = True

        # end_time = time.time()
        # elapsed_time = end_time - start_time

        # print("添加耗时：", elapsed_time, "秒")

        CURRENT_DIRECTORY = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

        depth_image = "dataImages/defect/image_20240130104608350_20240130104609334.bmp"
        # defect_mask = "dataImages/defect/image_20240130104608350_20240130104609334.png"
        defect_mask = "dataImages/defect/image_20240130110607271_20240130110610517.png"         
        # 结合 CURRENT_DIRECTORY 和 user_input 形成新的地址
        depth_image_path = os.path.join(CURRENT_DIRECTORY, depth_image)
        defect_mask_path = os.path.join(CURRENT_DIRECTORY, defect_mask)

        self.renderer.RemoveAllViewProps()

        self.actor = defectLoad(depth_image_path,defect_mask_path,'Mesh')

        center = self.actor.GetCenter()
        # self.renderer.AddActor(self.actor)

        # 计算相机应该放置的位置，这里我们简单地后退一定距离
        self.camera.SetPosition(center[0], center[1], center[2] + 600)
        self.camera.SetFocalPoint(center)
        self.hasLoadScene = True